﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace Assets.Scripts.LDS
{

    // Translate: Finished
    // Debug: 

    enum CommandType
    {
        Replace = 0,
        ReplaceWith,
        MoveTo,
        MoveOn,
        MoveCloser,
        MoveApart,
        Delete,
        Rotate
    };

    class TextSemGraph : SemanticGraph
    {
        private static readonly string[] CommandNames =
            { "replace", "replacewith", "moveto", "moveon", "movecloser", "moveapart", "delete", "rotate" };

        private int m_sentence_id;

        private List<int> m_isNodeCertain = new List<int>();
        private List<int> m_isNodeGrounded = new List<int>();
        private List<int> m_isEdgeGrounded = new List<int>();

        private RelationModelManager m_relModelManager;//generate
        private List<string> m_goodAttriSets = new List<string>();
        private List<string> m_goodGroupSets = new List<string>();

        public Dictionary<string, string> m_entityNameToNodeNameMap = new Dictionary<string, string>();
        public SelSentence m_sentence;//generate


        public TextSemGraph(SelSentence s, RelationModelManager relManager, bool isCommand = false)
        {
            m_sentence = s;
            // m_sentence = new SelSentence(s);  
            m_relModelManager = relManager;
            m_isCommand = isCommand;
            initAttriSets();
            buildGraphFromSEL();
        }


        void initAttriSets()
        {
            using (StreamReader sr = new StreamReader (Params.attributeListpth) )
            {
                string str = sr.ReadLine();
                m_goodAttriSets.AddRange(str.Split(','));

                str = sr.ReadLine();
                m_goodAttriSets.AddRange(str.Split(','));
                m_goodGroupSets.AddRange(str.Split(','));
            }

            //m_goodAttriSets.Add("office");
            //m_goodAttriSets.Add("coffee");
            //m_goodAttriSets.Add("dining");
            //m_goodAttriSets.Add("file");
            //m_goodAttriSets.Add("round");
            //m_goodAttriSets.Add("rectangular");
            //m_goodAttriSets.Add("sauce");
            //m_goodAttriSets.Add("queen");
            //m_goodAttriSets.Add("sofa");

            //m_goodAttriSets.Add("messy");
            //m_goodAttriSets.Add("formal");
            //m_goodAttriSets.Add("casual");
            //m_goodAttriSets.Add("organized");
            //m_goodAttriSets.Add("disorganized");
            //m_goodAttriSets.Add("clean");
            //m_goodAttriSets.Add("work");
            //m_goodAttriSets.Add("study");
        }
        

        void buildGraphFromSEL()
        {

            if (!m_isCommand)
            {
                // add object node
                List<string> addedObjNames = new List<string>();
                for (int i = 0; i < m_sentence.entityCount; i++)
                {
                    string nameString = m_sentence.m_entities[i].nameString;
                    //if (nameString.Contains("room") || nameString.Contains("wall")) continue;  // do not consider room in current implementation

                    List<string> parts = Util.PartitionString(nameString, "-");
                    string entityName = parts[0];
                    m_sentence.m_entities[i].nameString = entityName;
                    string determiner = m_sentence.m_entities[i].m_determiner;

                    // for plural form
                    if (m_sentence.m_entities[i].isPlural)
                    {
                        entityName = convertToSinglarForm(entityName);

                        string instanceCountString = m_sentence.m_entities[i].instanceCountString;

                        bool isNumber;

                        isNumber = int.TryParse(instanceCountString, out int instCount);   // no specified instance count is also counted 1

                        if (isNumber)
                        {
                            // since isPlural is true, add more instances; otherwise, use the given number
                            if (instCount == 1)
                            {
                                instCount = Util.GenRandomInt(2,4);

                                if (entityName == "monitor")
                                {
                                    instCount = 1;
                                }

                                if (entityName == "keyboard")
                                {
                                    instCount = 1;
                                }
                            }
                        }
                        else
                        {
                            if (instanceCountString == "some")
                            {
                                instCount = Util.GenRandomInt(2, 4);
                            }

                            if (instanceCountString == "many")
                            {
                                instCount = Util.GenRandomInt(3, 6);
                            }

                            if (entityName == "monitor")
                            {
                                instCount = 1;
                            }

                            if (entityName == "keyboard")
                            {
                                instCount = 1;
                            }
                        }

                        // special handling for books on shelf or cabinet
                        if (entityName == "book")
                        {
                            if (isOnObj(i, "shelf") || isWithObj(entityName, "shelf"))
                            {
                                entityName = "standbooks";
                                instCount = Util.GenRandomInt(2, 4);
                            }

                            if (isOnObj(i, "cabinet") || isWithObj(entityName, "cabinet"))
                            {
                                entityName = "stackbooks";
                                instCount = 1;
                            }
                        }

                        // add one node if determiner is the, and adjust the actual count when binding with current scene
                        if (determiner == "the")
                        {
                            instCount = 1;
                        }


                        m_sentence.m_entities[i].instanceCount = instCount;
                        for (int j = 0; j < m_sentence.m_entities[i].instanceCount; j++)
                        {
                            addNode("object", entityName);
                            m_isNodeCertain.Add(0);

                            int currNodeId = m_nodeNum - 1;
                            m_sentence.m_entities[i].m_instanceNodeIds.Add(currNodeId);

                            SemNode currNode = m_nodes[currNodeId];
                            if (determiner != "the")
                            {
                                currNode.useNewInst = true;
                            }
                        }

                        // update entity name
                        m_sentence.m_entities[i].nameString = entityName;
                        addedObjNames.Add(entityName);
                    }
                    // for single form
                    else
                    {
                        // if an entity appear multiple times, and some of them has determiner "the", then only insert one node for this instance
                        if (determiner == "the" && addedObjNames.Contains(entityName))
                            continue;

                        addNode("object", entityName);
                        m_isNodeCertain.Add(1);

                        int currNodeId = m_nodeNum - 1;
                        SemNode currNode = m_nodes[currNodeId];
                        if (determiner == "a")
                        {
                            currNode.useNewInst = true;
                        }

                        m_sentence.m_entities[i].m_instanceNodeIds.Add(m_nodeNum - 1);
                        m_sentence.m_entities[i].instanceCount = 1;
                        addedObjNames.Add(entityName);
                    }
                }

                // add relationship node
                for (int i = 0; i < m_sentence.entityCount; i++)
                {
                    string nameString = m_sentence.m_entities[i].nameString;
                    if (nameString.Contains("room") || nameString.Contains("wall")) continue;  // do not consider room in current implementation

                    int relationCount = m_sentence.m_entities[i].relationshipCount;

                    List<string> currRelationStrings = new List<string>(); // record current relation names; avoid duplicate
                    for (int j = 0; j < relationCount; j++)
                    {
                        string relationName = m_sentence.m_entities[i].m_relationships[j].nameString;
                        string relationRawString = m_sentence.m_entities[i].m_relationships[j].entityString;
                        if (currRelationStrings.Contains(relationRawString))
                        {
                            continue;
                        }

                        currRelationStrings.Add(relationRawString);

                        for (int n = 0; n < m_sentence.m_entities[i].instanceCount; n++)
                        {
                            string entityRawString = m_sentence.m_entities[i].m_relationships[j].entityString;
                            List<string> parts = Util.PartitionString(entityRawString, "-");
                            string anchorEntityName = parts[0];
                            anchorEntityName = convertToSinglarForm(anchorEntityName);

                            // special handling for books on shelf or cabinet
                            if (anchorEntityName == "book")
                            {
                                if (isWithObj(anchorEntityName, "shelf")) anchorEntityName = "standbooks";
                                if (isWithObj(anchorEntityName, "cabinet")) anchorEntityName = "stackbooks";
                            }

                            if (!relationName.Contains("aligned"))
                            {
                                List<int> refNodeIds = findNodeWithName(anchorEntityName);
                                for (int k = 0; k < refNodeIds.Count; k++)
                                {
                                    addNode("relation", relationName);

                                    int instanceNodeId = m_sentence.m_entities[i].m_instanceNodeIds[n];
                                    int currNodeId = m_nodeNum - 1;
                                    addEdge(instanceNodeId, currNodeId);
                                    addEdge(currNodeId, refNodeIds[k]);

                                    if (anchorEntityName == "wall")
                                    {
                                        m_nodes[currNodeId].nodeName = "horizonsupport";
                                    }
                                }
                            }
                        }

                        if (relationName.Contains("aligned"))
                        {
                            List<int> refNodeIds = findNodeWithName(nameString);

                            if (refNodeIds.Count > 1)
                            {
                                int anchorNodeId = refNodeIds[0];
                                for (int k = 1; k < refNodeIds.Count; k++)
                                {
                                    addNode("relation", relationName);

                                    int currNodeId = m_nodeNum - 1;
                                    addEdge(refNodeIds[k], currNodeId);
                                    addEdge(currNodeId, refNodeIds[0]);
                                }
                            }
                        }
                    }
                }

                // add attribute node
                for (int i = 0; i < m_sentence.entityCount; i++)
                {
                    int attributeCount = m_sentence.m_entities[i].attributeCount;
                    string entityName = m_sentence.m_entities[i].nameString;

                    for (int j = 0; j < attributeCount; j++)
                    {

                        string attriName = m_sentence.m_entities[i].m_attributes[j].nameString;

                        if (isGoodAttribute(attriName))
                        {
                            List<int> nodeIds = findNodeWithName(entityName);
                            for (int k = 0; k < nodeIds.Count; k++)
                            {
                                addNode("attribute", m_sentence.m_entities[i].m_attributes[j].nameString);
                                addEdge(m_nodeNum - 1, nodeIds[k]);
                            }
                        }
                    }
                }

                parseNodeNeighbors();

                mapNodeNameToFixedNameSet();

                addImplicitAttributes();
                addImplicitRelations();
                postProcessForSpecialRelations();
            }
            else
            {
                // add command
                for (int i = 0; i < m_sentence.commandCount; i++)
                {
                    string commandName = m_sentence.m_commands[i].verbString;
                    if (m_sentence.m_commands[i].attributeCount > 0)
                    {
                        commandName += m_sentence.m_commands[i].attributeStrings[0];
                    }

                    addNode("command", commandName);
                    int commandNodeId = m_nodeNum - 1;

                    for (int j = 0; j < m_sentence.m_commands[i].targetCount; j++)
                    {
                        string currTargetString = m_sentence.m_commands[i].targetStrings[j];
                        if (currTargetString.Contains("dobj"))
                        {
                            string directObjName = Util.PartitionString(currTargetString, "dobj|")[0];
                            directObjName = directObjName.Split('-')[0];

                            if (directObjName.EndsWith("s"))
                            {
                                directObjName = directObjName.Substring(0, directObjName.Length - 1);
                            }

                            addNode("object", directObjName);
                            int directObjId = m_nodeNum - 1;
                            addEdge(directObjId, commandNodeId);
                        }
                        else
                        {
                            string targetObjName = Util.PartitionString(currTargetString, "|")[1];
                            targetObjName = targetObjName.Split('-')[0];

                            if (targetObjName.EndsWith("s"))
                            {
                                targetObjName = targetObjName.Substring(0,targetObjName.Length - 1);
                            }

                            addNode("object", targetObjName);
                            int targetObjId = m_nodeNum - 1;
                            addEdge(commandNodeId, targetObjId);
                        }
                    }
                }

                mapNodeNameToFixedNameSet();
            }
        }

        //check finished


        public void mapNodeNameToFixedNameSet()
        {
            for (int i = 0; i < m_nodeNum; i++)
            {
                if (m_nodes[i].nodeType == "object")
                {
                    mapToFixedObjSet(ref m_nodes[i].nodeName);
                }

                if (m_nodes[i].nodeType.Contains("relation"))
                {
                    mapToFixedRelationSet(m_nodes[i], ref m_nodes[i].nodeName, ref m_nodes[i].nodeType);
                }

                if (m_nodes[i].nodeType == "attribute")
                {
                    mapToFixedAttributeSet(ref m_nodes[i].nodeName, ref m_nodes[i].nodeType);
                }

                if (m_nodes[i].nodeType == "command")
                {
                    mapToFixedCommandSet(ref m_nodes[i].nodeName, ref m_nodes[i].nodeType);
                }
            }

            parseNodeNeighbors();
        }

        // Map relation names to the Names in the ssg 

        void mapToFixedRelationSet(SemNode currNode, ref string nodeName, ref string nodeType /*= QString("")*/)
        {
            if (nodeName.Contains("on") && !nodeName.Contains("front") && !nodeName.Contains("along"))
            {
                // TODO: infer for horizonsupport
                if (nodeName.Contains("right"))
                {
                    nodeName = "onright";
                }
                else if (nodeName.Contains("left"))
                {
                    nodeName = "onleft";
                }
                else
                {
                    nodeName = "vertsupport";
                }

                nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                return;
            }

            if (nodeName.Contains("with"))
            {

                nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];

                // reverse edge dir
                SemEdge inEdge = getEdge(currNode.activeNodeList[0], currNode.nodeId);
                SemEdge outEdge = getEdge(currNode.nodeId, currNode.anchorNodeList[0]);
                inEdge.reverseEdgeDir();
                outEdge.reverseEdgeDir();

                // reverse for current node

                Util.Swap<List<int>>(ref currNode.activeNodeList, ref currNode.anchorNodeList);
                Util.Swap<List<int>>(ref currNode.inEdgeNodeList, ref currNode.outEdgeNodeList);


                int refNodeId = currNode.anchorNodeList[0];
                int actNodeId = currNode.activeNodeList[0];

                // correct relationship node id saved in the object node
                int currNodeId = currNode.nodeId;

                m_nodes[refNodeId].outEdgeNodeList.Remove(currNodeId);
                m_nodes[refNodeId].inEdgeNodeList.Add(currNodeId);

                m_nodes[actNodeId].inEdgeNodeList.Remove(currNodeId);
                m_nodes[actNodeId].outEdgeNodeList.Add(currNodeId);

                String anchorObjName = m_nodes[refNodeId].nodeName;
                String actObjName = m_nodes[actNodeId].nodeName;
                if (actObjName.Contains("book")) actObjName = "book";

                String suppRelKey1 = anchorObjName + "_" + actObjName + "_vertsupport";
                String suppRelKey2 = anchorObjName + "_" + actObjName + "_horizonsupport";


                if (m_relModelManager.m_supportRelations.ContainsKey(suppRelKey1))
                {
                    nodeName = "vertsupport";
                }
                else if (m_relModelManager.m_supportRelations.ContainsKey(suppRelKey2))
                {
                    nodeName = "horizonsupport";
                }
                else if (m_relModelManager.m_suppProbs.ContainsKey(actObjName) && m_relModelManager.m_suppProbs[actObjName].beChildProb >= 0.5
                    && m_relModelManager.m_suppProbs.ContainsKey(anchorObjName) && m_relModelManager.m_suppProbs[anchorObjName].beParentProb >= 0.5)
                {
                    nodeName = "vertsupport";
                }
                else
                {
                    nodeName = "near";
                }

                if ((anchorObjName == "tv" && actObjName == "speaker") ||
                    (anchorObjName == "bed" && actObjName == "nightstand"))
                {
                    nodeName = "side";
                }

                return;
            }

            if (nodeName == "next to" || nodeName == "close to" || nodeName == "near")
            {
                nodeName = "near";
                nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                return;
            }

            if (nodeName.Contains("front"))
            {
                nodeName = "front";
                nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                return;
            }

            if (nodeName.Contains("back") || nodeName.Contains("behind"))
            {
                nodeName = "back";
                nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                return;
            }

            if (nodeName.Contains("left"))
            {
                nodeName = "leftside";
                nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                return;
            }

            if (nodeName.Contains("right"))
            {
                nodeName = "rightside";
                nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                return;
            }

            if (nodeName.Contains("under") || nodeName.Contains("below"))
            {
                nodeName = "under";
                nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                return;
            }

            if (nodeName.Contains("center"))
            {
                nodeName = "oncenter";
                nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                return;
            }

            if (nodeName.Contains("stack"))
            {
                nodeName = "stacked";
                nodeType = SSGNodeType[(int)SemNode.NodeType.Group];
                return;
            }

            if (nodeName.Contains("each") && nodeName.Contains("side"))
            {
                nodeName = "leftside";
                nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                return;
            }

            if (nodeName == "around")
            {
                nodeName = "pairaround";
                nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                return;
            }

            if (nodeName.Contains("align"))
            {
                nodeName = "pairaligned";
                nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                return;
            }
        }


        // Map object names to Names in the ssg 
        public void mapToFixedObjSet(ref string nodeName)
        {
            if (nodeName == "sofa")
            {
                nodeName = "couch";
                m_entityNameToNodeNameMap["sofa"] = "couch";
                return;
            }

            if (nodeName == "desk")
            {
                nodeName = "table";
                m_entityNameToNodeNameMap["desk"] = "table";
                return;
            }


            if (nodeName == "pc")
            {
                nodeName = "computer";
                m_entityNameToNodeNameMap["pc"] = "computer";

                return;
            }

            if (nodeName == "mouse")
            {
                nodeName = "computermouse";
                m_entityNameToNodeNameMap["mouse"] = "computermouse";
                return;
            }

            if (nodeName.Contains("shelf"))
            {
                nodeName = "bookcase";
                m_entityNameToNodeNameMap["shelf"] = "bookcase";
                return;
            }

            if (nodeName == "headphone")
            {
                nodeName = "headphones";
                m_entityNameToNodeNameMap["headphone"] = "headphones";
                return;
            }

            if (nodeName == "socket")
            {
                nodeName = "powerstrip";
                m_entityNameToNodeNameMap["socket"] = "powerstrip";
                return;
            }

            if (nodeName == "clock")
            {
                nodeName = "tableclock";
                m_entityNameToNodeNameMap["clock"] = "tableclock";
                return;
            }

            if (nodeName == "frame")
            {
                //nodeName = "picturefame";
                nodeName = "framework";
                m_entityNameToNodeNameMap["frame"] = "framework";
                return;
            }

            //if (nodeName == "lamp")
            //{
            //    nodeName = "desklamp";
            //    m_entityNameToNodeNameMap["lamp"] = "desklamp";
            //    return;
            //}

            //if (nodeName == "cabinet")
            //{
            //    nodeName = "cabinet";
            //    m_entityNameToNodeNameMap["cabinet"] = "cabinet";
            //    return;
            //}
        }

        // Only take Good Attri into count
        void mapToFixedAttributeSet(ref string nodeName, ref string nodeType)
        {
            if (m_goodGroupSets.Contains(nodeName))
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Group];
            }
            else
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Attri];
            }

            return;

            if (nodeName == "office")
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Attri];
                return;
            }

            if (nodeName == "coffee")
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Attri];
                return;
            }

            if (nodeName == "dining")
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Attri];
                return;
            }

            if (nodeName == "file")
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Attri];
                return;
            }

            if (nodeName == "round")
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Attri];
                return;
            }

            if (nodeName == "rectangular")
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Attri];
                return;
            }

            if (nodeName == "sauce")
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Attri];
                return;
            }

            if (nodeName.Contains("messy"))
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Group];
                nodeName = "messy";
                return;
            }

            if (nodeName.Contains("formal"))
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Group];
                nodeName = "formal";
                return;
            }

            if (nodeName.Contains("casual"))
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Group];
                nodeName = "casual";
                return;
            }

            if (nodeName.Contains("organize") && !nodeName.Contains("dis"))
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Group];
                nodeName = "organized";
                return;
            }

            if (nodeName.Contains("disorganize"))
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Group];
                nodeName = "messy";
                return;
            }

            if (nodeName.Contains("clean"))
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Group];
                nodeName = "clean";
                return;
            }

            if (nodeName.Contains("work"))
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Group];
                nodeName = "work";
                return;
            }

            if (nodeName.Contains("study"))
            {
                nodeType = SSGNodeType[(int)SemNode.NodeType.Group];
                nodeName = "study";
                return;
            }
        }


        void mapToFixedCommandSet(ref string nodeName, ref string nodeType)
        {
        }

        //......for the example in paper ->_->
        void addImplicitAttributes()
        {
            if (m_sentence.textString.Contains("dining table"))
            {
                for (int i = 0; i < m_nodes.Count; i++)
                {
                    SemNode currNode = m_nodes[i];
                    if (currNode.nodeName == "chair")
                    {
                        List<String> relNames = new List<string>();
                        for (int r = 0; r < currNode.inEdgeNodeList.Count; r++)
                        {
                            int relNodeId = currNode.inEdgeNodeList[r];
                            SemNode relNode = m_nodes[relNodeId];
                            relNames.Add(relNode.nodeName);
                        }

                        if (!relNames.Contains("dining"))
                        {
                            addNode(SSGNodeType[(int)SemNode.NodeType.Attri], "dining");

                            int currNodeId = m_nodeNum - 1;
                            addEdge(currNodeId, i);
                        }
                    }
                }
            }

            parseNodeNeighbors();
        }// add implicit attributes of objects, e.g., dining to chair if a dining table is specified


        void addImplicitRelations()
        {
            for (int i = 0; i < m_nodes.Count; i++)
            {
                SemNode currNode = m_nodes[i];
                if (currNode.nodeName == "couch" && currNode.inEdgeNodeList.Count == 0)
                {
                    for (int j = 0; j < m_nodes.Count; j++)
                    {
                        if (i == j) continue;
                        SemNode actNode = m_nodes[j];
                        if (actNode.nodeName == "chair" && actNode.outEdgeNodeList.Count == 0)
                        {
                            addNode(SSGNodeType[(int)SemNode.NodeType.Pair], "near");

                            int currNodeId = m_nodeNum - 1;
                            addEdge(j, currNodeId);
                            addEdge(currNodeId, i);
                        }
                    }
                }
            }

            parseNodeNeighbors();
        } // add implicit relations if no relations specified in the input

        public string convertToSinglarForm(string s)
        {
            string singleS;
            // e.g. shelves
            if (s.EndsWith("ves"))
            {
                singleS = s.Substring(0, s.Length - 3);
                singleS += "f";
            }
            // e.g. books
            else if (s.EndsWith("s"))
            {
                singleS = s.Substring(0, s.Length - 1);
            }
            else
            {
                singleS = s;
            }

            return singleS;
        }

        public bool isOnObj(int entityId, string anchorName)
        {
            int relationCount = m_sentence.m_entities[entityId].relationshipCount;

            for (int j = 0; j < relationCount; j++)
            {
                string entityRawString = m_sentence.m_entities[entityId].m_relationships[j].entityString;
                if (entityRawString.Contains(anchorName))
                {
                    return true;
                }
            }

            return false;
        }
        public bool isWithObj(string currObjName, string anchorName)
        {
            // find anchor
            for (int i = 0; i < m_sentence.entityCount; i++)
            {
                string nameString = m_sentence.m_entities[i].nameString;
                if (nameString.Contains(anchorName))
                {
                    int relationCount = m_sentence.m_entities[i].relationshipCount;

                    for (int j = 0; j < relationCount; j++)
                    {
                        string entityRawString = m_sentence.m_entities[i].m_relationships[j].entityString;
                        if (entityRawString.Contains(currObjName))
                        {
                            return true;
                        }
                    }
                }
            }

            return false;
        }

        public bool isGoodAttribute(string attriName)
        {
            return m_goodAttriSets.Contains(attriName);
        }


        public string getDeterminerOfEntity(string nodeName)
        {
            string determiner = "";

            for (int i = 0; i < m_sentence.entityCount; i++)
            {
                string nameString = m_sentence.m_entities[i].nameString;

                string outvalue = "";
                if (! m_entityNameToNodeNameMap.TryGetValue(nameString, out outvalue)) continue;
                if (outvalue == nodeName)
                {
                    determiner = m_sentence.m_entities[i].m_determiner;
                    return determiner;
                }
            }

            return determiner;
        }



        void postProcessForSpecialRelations()
        {
            if (m_sentence.textString.Contains("each side") || m_sentence.textString.Contains("eachside"))
            {
                List<int> relNodelIds = new List<int>();
                for (int i = 0; i < m_nodeNum; i++)
                {
                    if (m_nodes[i].nodeName.Contains("side"))
                    {
                        relNodelIds.Add(i);
                    }
                }

                for (int i = 0; i < relNodelIds.Count / 2; i++)
                {
                    int relNodeId = relNodelIds[i];
                    SemNode relNode = m_nodes[relNodeId];

                    if (relNode.anchorNodeList.Count > 0)
                    {
                        int anchorNodeId = relNode.anchorNodeList[0];
                        SemNode anchorNode = m_nodes[anchorNodeId];
                        if (anchorNode.nodeName != "table")
                        {
                            m_nodes[relNodeId].nodeName = "leftside";
                            m_nodes[relNodeId].nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                        }
                    }
                }

                for (int i = relNodelIds.Count / 2; i < relNodelIds.Count; i++)
                {

                    int relNodeId = relNodelIds[i];
                    SemNode relNode = m_nodes[relNodeId];

                    if (relNode.anchorNodeList.Count > 0)
                    {
                        int anchorNodeId = relNode.anchorNodeList[0];
                        SemNode anchorNode = m_nodes[anchorNodeId];
                        if (anchorNode.nodeName != "table")
                        {
                            m_nodes[relNodeId].nodeName = "rightside";
                            m_nodes[relNodeId].nodeType = SSGNodeType[(int)SemNode.NodeType.Pair];
                        }
                    }
                }
            }
        }


    }
}
